package com.example.mapdsl;

import com.example.mapdsl.dsl.MapDSLBaseVisitor;
import com.example.mapdsl.dsl.MapDSLParser;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * DSL访问者实现类，用于解释和执行DSL脚本
 * 继承自ANTLR自动生成的BaseVisitor类，处理所有语法规则
 */
public class MapDSLVisitorImpl extends MapDSLBaseVisitor<Object> {
    /** 存储DSL中定义的变量 */
    private final Map<String, Object> variables = new HashMap<>();
    /** 待处理的数据，在DSL中通过'data'关键字访问 */
    private final Map<String, String> data;

    /**
     * 构造函数
     * @param data 待处理的Map数据
     */
    public MapDSLVisitorImpl(Map<String, String> data) {
        this.data = data;
    }

    /**
     * 访问程序入口，处理所有语句
     * @param ctx 程序上下文
     * @return 执行结果列表
     */
    @Override
    public Object visitProgram(MapDSLParser.ProgramContext ctx) {
        List<Object> results = new ArrayList<>();
        for (MapDSLParser.StatementContext statement : ctx.statement()) {
            results.add(visit(statement));
        }
        return results;
    }

    /**
     * 处理变量声明语句
     * 格式: var 变量名 = 表达式;
     */
    @Override
    public Object visitVariableDeclaration(MapDSLParser.VariableDeclarationContext ctx) {
        String name = ctx.IDENTIFIER().getText();
        Object value = visit(ctx.expression());
        variables.put(name, value);
        return null;
    }

    /**
     * 处理if语句
     * 格式: if (条件) { 语句块 } else { 语句块 }
     */
    @Override
    public Object visitIfStatement(MapDSLParser.IfStatementContext ctx) {
        Object condition = visit(ctx.expression());
        if (!(condition instanceof Boolean)) {
            throw new RuntimeException("If condition must be boolean");
        }
        
        if ((Boolean) condition) {
            return visit(ctx.block(0));
        } else if (ctx.block(1) != null) {
            return visit(ctx.block(1));
        }
        return null;
    }

    /**
     * 处理代码块
     * 格式: { 语句* }
     */
    @Override
    public Object visitBlock(MapDSLParser.BlockContext ctx) {
        for (MapDSLParser.StatementContext statement : ctx.statement()) {
            visit(statement);
        }
        return null;
    }

    /**
     * 处理方法调用表达式
     * 主要用于处理data对象的方法调用，如data.get("key")
     */
    @Override
    public Object visitMethodCallExpr(MapDSLParser.MethodCallExprContext ctx) {
        Object target = visit(ctx.expression(0));
        String methodName = ctx.IDENTIFIER().getText();
        
        if (target == data) {
            List<Object> args = new ArrayList<>();
            for (int i = 1; i < ctx.expression().size(); i++) {
                args.add(visit(ctx.expression(i)));
            }
            return executeMapMethod(methodName, args);
        }
        
        throw new RuntimeException("Method calls only supported on 'data' object");
    }

    /**
     * 处理基本表达式
     * 包括：整数、浮点数、布尔值、字符串、变量引用和data关键字
     */
    @Override
    public Object visitPrimary(MapDSLParser.PrimaryContext ctx) {
        if (ctx.INTEGER() != null) {
            return Integer.parseInt(ctx.INTEGER().getText());
        }
        if (ctx.FLOAT() != null) {
            return Double.parseDouble(ctx.FLOAT().getText());
        }
        if (ctx.BOOLEAN() != null) {
            return Boolean.parseBoolean(ctx.BOOLEAN().getText());
        }
        if (ctx.STRING() != null) {
            String text = ctx.STRING().getText();
            return text.substring(1, text.length() - 1); // 移除引号
        }
        if (ctx.STRING_ARRAY() != null) {
            String text = ctx.STRING_ARRAY().getText();
            // 移除首尾的[]括号
            text = text.substring(1, text.length() - 1).trim();
            List<String> array = new ArrayList<>();
            if (!text.isEmpty()) {
                // 分割字符串并处理每个元素
                for (String item : text.split(",")) {
                    item = item.trim();
                    // 移除每个元素的引号
                    array.add(item.substring(1, item.length() - 1));
                }
            }
            return array;
        }
        if (ctx.IDENTIFIER() != null) {
            String id = ctx.IDENTIFIER().getText();
            if (!variables.containsKey(id)) {
                throw new RuntimeException("Undefined variable: " + id);
            }
            return variables.get(id);
        }
        if (ctx.getText().equals("data")) {
            return data;
        }
        return visit(ctx.expression());
    }

    /**
     * 处理逻辑非运算
     * 格式: !表达式
     */
    @Override
    public Object visitNotExpr(MapDSLParser.NotExprContext ctx) {
        Object value = visit(ctx.expression());
        if (!(value instanceof Boolean)) {
            throw new RuntimeException("Operator '!' can only be applied to boolean values");
        }
        return !(Boolean) value;
    }

    /**
     * 处理乘法表达式
     * 支持: *, /, %
     */
    @Override
    public Object visitMultiplicativeExpr(MapDSLParser.MultiplicativeExprContext ctx) {
        Object left = visit(ctx.expression(0));
        Object right = visit(ctx.expression(1));
        String op = ctx.op.getText();
        
        if (left instanceof Number && right instanceof Number) {
            double l = ((Number) left).doubleValue();
            double r = ((Number) right).doubleValue();
            
            switch (op) {
                case "*": return l * r;
                case "/": return l / r;
                case "%": return l % r;
                default: throw new RuntimeException("Unknown operator: " + op);
            }
        }
        throw new RuntimeException("Arithmetic operations require numeric operands");
    }

    /**
     * 处理加法表达式
     * 支持: +, -
     * 特殊处理: 字符串连接
     */
    @Override
    public Object visitAdditiveExpr(MapDSLParser.AdditiveExprContext ctx) {
        Object left = visit(ctx.expression(0));
        Object right = visit(ctx.expression(1));
        String op = ctx.op.getText();

        if (left instanceof String || right instanceof String) {
            return String.valueOf(left) + String.valueOf(right);
        }
        
        if (left instanceof Number && right instanceof Number) {
            double l = ((Number) left).doubleValue();
            double r = ((Number) right).doubleValue();
            
            return op.equals("+") ? l + r : l - r;
        }
        throw new RuntimeException("Invalid operands for " + op);
    }

    /**
     * 执行Map对象的方法
     * @param methodName 方法名
     * @param args 参数列表
     * @return 方法执行结果
     */
    private Object executeMapMethod(String methodName, List<Object> args) {
        switch (methodName) {
            case "get": return data.get(args.get(0).toString());
            case "put": return data.put(args.get(0).toString(), args.get(1).toString());
            case "remove": return data.remove(args.get(0).toString());
            case "containsKey": return data.containsKey(args.get(0).toString());
            case "containsValue": return data.containsValue(args.get(0).toString());
            case "size": return data.size();
            case "isEmpty": return data.isEmpty();
            case "keySet": return data.keySet();
            default: throw new RuntimeException("Unknown method: " + methodName);
        }
    }

    /**
     * 处理关系运算表达式 (>, >=, <, <=)
     * 支持数值和字符串的比较
     * @param ctx 关系表达式上下文
     * @return 比较结果的布尔值
     */
    @Override
    public Object visitRelationalExpr(MapDSLParser.RelationalExprContext ctx) {
        Object left = visit(ctx.expression(0));
        Object right = visit(ctx.expression(1));
        String op = ctx.op.getText();

        // 处理数值比较
        if (left instanceof Number && right instanceof Number) {
            double l = ((Number) left).doubleValue();
            double r = ((Number) right).doubleValue();
            switch (op) {
                case ">": return l > r;
                case ">=": return l >= r;
                case "<": return l < r;
                case "<=": return l <= r;
                default: throw new RuntimeException("Unknown operator: " + op);
            }
        }

        // 处理字符串比较
        if (left instanceof String && right instanceof String) {
            int comparison = ((String) left).compareTo((String) right);
            switch (op) {
                case ">": return comparison > 0;
                case ">=": return comparison >= 0;
                case "<": return comparison < 0;
                case "<=": return comparison <= 0;
                default: throw new RuntimeException("Unknown operator: " + op);
            }
        }

        throw new RuntimeException("Invalid operands for " + op + ": " + left + ", " + right);
    }

    /**
     * 处理相等性比较表达式 (==, !=)
     * 支持null值、数值和一般对象的比较
     * @param ctx 相等性表达式上下文
     * @return 比较结果的布尔值
     */
    @Override
    public Object visitEqualityExpr(MapDSLParser.EqualityExprContext ctx) {
        Object left = visit(ctx.expression(0));
        Object right = visit(ctx.expression(1));
        String op = ctx.op.getText();

        // 处理null值比较
        if (left == null || right == null) {
            return op.equals("==") ? (left == right) : (left != right);
        }

        // 处理数值比较
        if (left instanceof Number && right instanceof Number) {
            double l = ((Number) left).doubleValue();
            double r = ((Number) right).doubleValue();
            return op.equals("==") ? l == r : l != r;
        }

        // 处理一般对象比较
        return op.equals("==") ? left.equals(right) : !left.equals(right);
    }

    /**
     * 处理逻辑与表达式 (&&)
     * @param ctx 逻辑与表达式上下���
     * @return 逻辑运算结果
     * @throws RuntimeException 如果操作数不是布尔值
     */
    @Override
    public Object visitAndExpr(MapDSLParser.AndExprContext ctx) {
        Object left = visit(ctx.expression(0));
        Object right = visit(ctx.expression(1));

        // 检查操作数类型
        if (!(left instanceof Boolean) || !(right instanceof Boolean)) {
            throw new RuntimeException("Operator '&&' can only be applied to boolean values, but got: " + 
                                     "left=" + (left == null ? "null" : left.getClass().getSimpleName()) + 
                                     ", right=" + (right == null ? "null" : right.getClass().getSimpleName()));
        }

        return (Boolean)left && (Boolean)right;
    }

    /**
     * 处理逻辑或表达式 (||)
     * @param ctx 逻辑或表达式上下文
     * @return 逻辑运算结果
     * @throws RuntimeException 如果操作数不是布尔值
     */
    @Override
    public Object visitOrExpr(MapDSLParser.OrExprContext ctx) {
        Object left = visit(ctx.expression(0));
        Object right = visit(ctx.expression(1));

        // 检查操作数类型
        if (!(left instanceof Boolean) || !(right instanceof Boolean)) {
            throw new RuntimeException("Operator '||' can only be applied to boolean values, but got: " + 
                                     "left=" + (left == null ? "null" : left.getClass().getSimpleName()) + 
                                     ", right=" + (right == null ? "null" : right.getClass().getSimpleName()));
        }

        return (Boolean)left || (Boolean)right;
    }

    /**
     * 处理正则表达式匹配
     * @param ctx 正则表达式匹配上下文
     * @return 匹配结果的布尔值
     * @throws RuntimeException 如果参数不是字符串或正则表达式无效
     */
    @Override
    public Object visitRegexMatchExpr(MapDSLParser.RegexMatchExprContext ctx) {
        Object str = visit(ctx.expression(0));
        Object pattern = visit(ctx.expression(1));
        
        // 检查参数类型
        if (!(str instanceof String) || !(pattern instanceof String)) {
            throw new RuntimeException("reg_match requires string arguments");
        }
        
        try {
            return ((String) str).matches((String) pattern);
        } catch (java.util.regex.PatternSyntaxException e) {
            throw new RuntimeException("Invalid regular expression: " + e.getMessage());
        }
    }

    /**
     * 处理数组大小表达式
     * 格式: size(array)
     * @param ctx 数组大小表达式上下文
     * @return 数组��长度
     * @throws RuntimeException 如果参数不是字符串数组
     */
    @Override
    public Object visitArraySizeExpr(MapDSLParser.ArraySizeExprContext ctx) {
        Object array = visit(ctx.expression());
        
        if (array instanceof List<?>) {
            return ((List<?>) array).size();
        } else if (array instanceof String[]) {
            return ((String[]) array).length;
        }
        
        throw new RuntimeException("size() function requires array argument, but got: " + 
                                 (array == null ? "null" : array.getClass().getSimpleName()));
    }

    /**
     * 处理正则表达式替换
     * 格式: reg_replace(str, pattern, replacement)
     * @param ctx 正则表达式替换上下文
     * @return 替换后的字符串
     * @throws RuntimeException 如果参数类型不正确或正则表达式无效
     */
    @Override
    public Object visitRegexReplaceExpr(MapDSLParser.RegexReplaceExprContext ctx) {
        Object str = visit(ctx.expression(0));
        Object pattern = visit(ctx.expression(1));
        Object replacement = visit(ctx.expression(2));
        
        if (!(str instanceof String) || !(pattern instanceof String) || !(replacement instanceof String)) {
            throw new RuntimeException("reg_replace requires string arguments");
        }
        
        try {
            return ((String) str).replaceAll((String) pattern, (String) replacement);
        } catch (java.util.regex.PatternSyntaxException e) {
            throw new RuntimeException("Invalid regular expression in reg_replace: " + e.getMessage());
        }
    }

    /**
     * 处理正则表达式查找所有匹配
     * 格式: reg_findall(str, pattern)
     * @param ctx 正则表达式查找上下文
     * @return 匹配的字符串数组
     * @throws RuntimeException 如果参数类型不正确或正则表达式无效
     */
    @Override
    public Object visitRegexFindAllExpr(MapDSLParser.RegexFindAllExprContext ctx) {
        Object str = visit(ctx.expression(0));
        Object pattern = visit(ctx.expression(1));
        
        if (!(str instanceof String) || !(pattern instanceof String)) {
            throw new RuntimeException("reg_findall requires string arguments");
        }
        
        try {
            java.util.regex.Pattern p = java.util.regex.Pattern.compile((String) pattern);
            java.util.regex.Matcher m = p.matcher((String) str);
            List<String> matches = new ArrayList<>();
            while (m.find()) {
                matches.add(m.group());
            }
            return matches;
        } catch (java.util.regex.PatternSyntaxException e) {
            throw new RuntimeException("Invalid regular expression in reg_findall: " + e.getMessage());
        }
    }

    /**
     * 处理数组访问表达式
     * 格式: array[index]
     */
    @Override
    public Object visitArrayAccessExpr(MapDSLParser.ArrayAccessExprContext ctx) {
        Object array = visit(ctx.expression(0));
        Object index = visit(ctx.expression(1));
        
        if (!(array instanceof List)) {
            throw new RuntimeException("Cannot use array access on non-array type: " + 
                                     (array == null ? "null" : array.getClass().getSimpleName()));
        }
        
        if (!(index instanceof Number)) {
            throw new RuntimeException("Array index must be a number");
        }
        
        List<?> list = (List<?>) array;
        int idx = ((Number) index).intValue();
        
        if (idx < 0 || idx >= list.size()) {
            throw new RuntimeException("Array index out of bounds: " + idx);
        }
        
        return list.get(idx);
    }
} 